/**
 * 
 */
package test.temp.suanfa;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import hyl.core.MyFun;
import hyl.core.run.IDo1;
import hyl.core.run.IDoEach1;
import hyl.core.run.IFilter;
import hyl.core.struct.MyNode;

/**
 * 
 * 
 * 2022年9月26日
 * 
 */
public class TApi {
	int 计算日期;
	long 抢单日总业绩 = 0;
	long 抢单日总计算金 = 0;
	static List<T抢单> 日抢单交易记录 = new ArrayList<>();
	static List<T交易> 日商城交易记录 = new ArrayList<>();
	static List<T打赏> 日打赏记录 = new ArrayList<>();
	static List<T释放> 待释放记录 = new ArrayList<>();
	static List<T记账> 日抢单记账记录 = new ArrayList<>();
	static List<T记账> 日商城记账记录 = new ArrayList<>();
	static Set<UserInfo> 日抢单买方节点 = new HashSet<>();

	public TApi() {
		计算日期 = MyFun.getYYYYMMDD();
	}

	public TApi(Integer yyyymmdd) {
		计算日期 = yyyymmdd == null ? MyFun.getYYYYMMDD() : yyyymmdd;
	}

//导入
	void load用户集合() {

	}

	public void f001_抢单日结_初始化() {
		抢单日总业绩 = 0;
		抢单日总计算金 = 0;
		List<List<Object>> 用户集 = new ArrayList<>();

		// 从数据库导入用户数据到用户集合=====================
		// 用户集.add(new ArrayList<>());

		// 读取用户到所有用户集合,排序用户编号从小到大
		for (List<?> u : 用户集) {
			UserInfo u1 = UserInfo.所有用户.get(u.get(0));// 0 自身id
			int tjr = MyFun.obj2Int(u.get(1), 0);// 1 :推荐人
			if (tjr == 0) {
				u1.set父节点(UserInfo._根节点);// 挂载父节点
			} else {
				UserInfo u2 = UserInfo.所有用户.get(tjr);// 1 推荐人编号
				u1.set父节点(u2);// 挂载父节点
			}
			u1.f抢单结算前重置();
		}
		UserInfo.f预遍历();
		// 遍历用户集合中的每个用户挂载到指定父节点

	}

//测试时专用
	public void test001_抢单日结_初始化() {
		抢单日总业绩 = 0;
		for (UserInfo u1 : UserInfo.所有用户.values()) {
			u1.f抢单结算前重置();
		}
		UserInfo.f预遍历();
	}

//??? 从数据库提取并导入
	public void f002_抢单日结_导入抢单交易记录() {
		// 有效可以结算奖金(已付款的) 的抢单记录全部导入到对象模型
		// 日竞拍交易记录

	}

	public void f004_抢单日结_遍历抢单记录() {
		// 遍历 VIP", "团长","社区", "区县", "市", "省" 六种角色,分别计算和标记满足角色的人 的新角色
		// 计算总业绩和个人业绩
		long 业绩 = 0;

		for (T抢单 jy : 日抢单交易记录) {
			// 累计个人的抢单次数
			if (jy.i抢单状态.get() == T抢单.D已付款 || jy.i抢单状态.get() == T抢单.D止拍) {// 只有付款的单子才算业绩
				// 累计个人的个人业绩
				jy.u买方.i当日抢单次数++;
				业绩 = jy.get售价();

				jy.u买方.i抢单日业绩 += 业绩;
				jy.u买方.l抢单日手续费 += jy.I手续费;

				抢单日总业绩 += 业绩;
				抢单日总计算金 += jy.I手续费;

				UserInfo 推荐人 = (UserInfo) jy.u买方._nd父节点;
				long 提成 = jy.I手续费 * D参.i转拍销售提成 / D参.比例1000;
				String msg = MyFun.join("转拍(直接)销售提成给买方的推荐人", 推荐人.s手机, ",手续费*销售提成=", jy.I手续费, "*", D参.i转拍销售提成, "‰");
				推荐人.记抢单动态收益(提成, jy.i手续费类型, D参.D科目_竞拍_转拍提成, msg);

				日抢单买方节点.add(jy.u买方);
				

			} else if (jy.i抢单状态.get() == T抢单.D已抢单) {// 只是抢单没有成功付款时
				// 卖方可以得到静态奖金 2% ,抢单时已经结算
				// 公司得到8%
				long 流拍到公司 = jy.I成本 * (D参.I流拍扣减 - D参.M酬金系数[3]) * D参.比例1000;
				UserInfo 平台 = UserInfo.getUser(UserInfo.平台ID);
				平台.记流拍账(流拍到公司, D参.D科目_竞拍_流拍补偿, "流拍后补偿公司8%");
			}
		}

		// 所有抢单角色从0开始动态升级
		// 更新用户的抢单角色,
		// 此处遍历算法 评估过了 没有问题

		for (UserInfo u : 日抢单买方节点) {

			u.up((nd) -> {
				UserInfo 子 = (UserInfo) nd;
				// System.out.println(子._id+ " "+子.i当日抢单次数);
				if (nd == UserInfo._根节点)
					return;
				UserInfo 父 = (UserInfo) nd._nd父节点;
				if (子.i当日抢单次数 > 1) {
					父.nd子节点中抢单两次人员.add(子);
				}
				父.l抢单日团队业绩 += u.i抢单日业绩;
			});
		}
		// System.out.println("--------------004.0-------------");
		List<UserInfo> 加盟商列表 = UserInfo.抢单用户分组.get(1);
		// 标记加盟商角色
		UserInfo.f广度遍历向上((i, nd) -> {
			UserInfo 父 = (UserInfo) nd._nd父节点;
			// 加盟商
			if (nd.i抢单角色 == 0 && 父.i抢单角色 == 0 && 父.nd子节点中抢单两次人员.size() > 2 //
					&& 父.i当日抢单次数 > 1) { // 要求升级vip的节点自己也要抢单2次
				父.i抢单角色 = 1;
				加盟商列表.add(父);
				return true;
			}
			return false;
		});

		// System.out.println("--------------004.1-------------");

		// 标记加盟商以上的更高级角色
		for (UserInfo nd : 加盟商列表) {
			NB004_标记加盟商之上的会员角色 t1 = new NB004_标记加盟商之上的会员角色(nd);
			nd.up(t1);
		}
		System.out.println("-------------004.4--------------");
		// UserInfo.showAll();
		// UserInfo.show集合(列表1);
		UserInfo._根节点.down2(0, (i, nd) -> {
			UserInfo 节点 = (UserInfo) nd;
			if (节点.i抢单角色 > 1) {
				UserInfo.抢单用户分组.get(节点.i抢单角色).add(节点);
			}
			return false;
		}, null);

	}

	class NB004_标记加盟商之上的会员角色 implements IDo1<MyNode<Integer, String>> {

		UserInfo 叶节点;
		int 下级 = 0;

		NB004_标记加盟商之上的会员角色(UserInfo 当前) {
			叶节点 = 当前;
			下级 = 叶节点.i抢单角色;
		}

		@Override
		public void run(MyNode<Integer, String> nnd) {
			if (nnd == null || nnd == 叶节点)
				return;
			UserInfo 上节点 = (UserInfo) nnd;
			int 人数 = 上节点.get抢单达标团队数(下级, 0);
			if (人数 >= D参.D伞下抢单条件[下级]) {
				int 升级 = 下级;
				if (下级 == 1) {
					if (上节点.i当日抢单次数 > 1)// 团长要求自己必须抢单2次
						升级 = 下级 + 1;
				} else
					升级 = 下级 + 1;
				if (上节点.i抢单角色 < 升级 && 升级 < 6) {
					上节点.i抢单角色 = 升级;
					下级 = 升级;
				}
			}
			return;
		}

	}

	public void f005_抢单日结_计算抢单分红() {
		//
		System.out.println("-------------抢单 005.1--------------");
		for (T抢单 qd : 日抢单交易记录) {
			// qd 4.2%结算到平台
			String msg = MyFun.join("交给平台手续费=买方手续费*", (float) D参.i竞拍手续费 / D参.比例1000);
			UserInfo.记平台收益(qd.i手续费类型, qd.I手续费 * D参.i竞拍手续费 / D参.比例1000, D参.D科目_竞拍_竞拍手续费, qd.u买方, msg);
			qd.u买方.up((nd) -> {
				if (nd == null || nd == UserInfo._根节点 || nd == qd.u买方)
					return;
				f006_抢单日结_计算单笔抢单分红(qd, (UserInfo) nd);
			});
		}
		System.out.println("-------------抢单 005.2--------------");
		Map<Integer, Long> 日合计收益 = new HashMap<>();
		Map<Integer, Long> 日合计仓金 = new HashMap<>();
		for (T记账 jz : 日抢单记账记录) {
			if (jz.i手续费类型 == 1) {
				Long 原值 = 日合计收益.get(jz.u用户._id);
				原值 = MyFun.nvl(原值, 0L);
				日合计收益.put(jz.u用户._id, 原值 + jz.l长值);
			} else if (jz.i手续费类型 == 2) {
				Long 原值 = 日合计仓金.get(jz.u用户._id);
				原值 = MyFun.nvl(原值, 0L);
				日合计仓金.put(jz.u用户._id, 原值 + jz.l长值);
			}
			// System.out.println(idString);
		}
		System.out.println("-------------抢单 005.3--------------");
		for (Map.Entry<Integer, Long> 记录 : 日合计收益.entrySet()) {
			// String t = JSON.toJSONString(记录);
			// System.out.println(t);
			UserInfo u = UserInfo.getUser(记录.getKey());
			u.记抢单动态收益(记录.getValue(), 1, D参.D科目_竞拍_分红, "抢单分红");
		}
		for (Map.Entry<Integer, Long> 记录 : 日合计仓金.entrySet()) {
			// String t = JSON.toJSONString(记录);
			// System.out.println(t);
			UserInfo u = UserInfo.getUser(记录.getKey());
			u.记抢单动态收益(记录.getValue(), 2, D参.D科目_竞拍_分红, "抢单仓金分红");
		}
	}

	/**
	 * 
	 * 根据抢单的日志记录 结算酬金
	 */
	public void f006_抢单日结_计算单笔抢单分红(T抢单 抢单, UserInfo 分红者) {
		int 角色 = 分红者.i抢单角色;
		long M3 = D参.MM奖金(抢单.I手续费, 角色);

		List<UserInfo> li = UserInfo.抢单用户分组.get(角色);
		int n = li.size();
		if (n == 0)
			return;
		if (角色 > 0 && 角色 < 4) {
			long M4 = M3 / 2;
			long 平均 = M4 / n;
			for (int i = 0; i < n; i++) {
				UserInfo u1 = li.get(i);
				f005_1抢单动态收益(u1, 抢单.i手续费类型, 抢单.l抢单时间戳, 平均, D参.D科目_竞拍_平均提成);
				int 业绩 = (int) ((long) M4 * u1.l抢单日团队业绩 / 抢单日总业绩);
				f005_1抢单动态收益(u1, 抢单.i手续费类型, 抢单.l抢单时间戳, 业绩, D参.D科目_竞拍_业绩提成);
			}
		} else if (角色 > 3 && 角色 < 7) {
			long 代理奖 = M3 / n;
			for (int i = 0; i < n; i++) {
				UserInfo u1 = li.get(i);
				f005_1抢单动态收益(u1, 抢单.i手续费类型, 抢单.l抢单时间戳, 代理奖, D参.D科目_竞拍_代理奖);
			}
		}
	}

	/**
	 * 可以记录到数据库某记录表,也可以不记,在内存中直接汇总
	 * 
	 * @param 用户
	 * @param 手续费类型
	 * @param 时间戳
	 * @param 金额
	 * @param 科目
	 */
	public static void f005_1抢单动态收益(UserInfo 用户, int 手续费类型, long 时间戳, long 金额, int 科目) {
		///////////// 插入数据库记录

		// String msg = MyFun.join("{金额:", 金额, ",UID:", 用户._id, ",科目:", 科目, "}");
		// 用户 科目 金额
		String msg = MyFun.join2("\t", "日抢单记录分解:", 用户._id, 科目, 金额, 时间戳);
		// 插入数据库
		日抢单记账记录.add(new T记账(用户, 手续费类型, 科目, 金额));
		System.out.println(msg);
	}

//购买99 199 等交易时触发
	public void f商城交易100_送云值(T交易 交易) {
		TApi.日商城交易记录.add(交易);
		交易.u买方.upUntil(new NB100_商城交易送云值(交易));
	}

	class NB100_商城交易送云值 implements IFilter<MyNode<Integer, String>> {

		Long 云值奖金 = 0l;
		int 下层角色 = 0;
		long yz = 0;
		T交易 交易;

		boolean is升级 = false;

		public NB100_商城交易送云值(T交易 c交易) {
			交易 = c交易;
			yz = 交易.I奖励云值;// 放大1万倍
		}

		@Override
		public boolean where(MyNode<Integer, String> obj) {
			UserInfo r = (UserInfo) obj;
			int 当前角色 = r.i商城角色;
			// 如果是自身节点
			if (r == 交易.u买方) {
				r.l日赠云值 += yz;
				交易.u买方.记用户云值(交易.l交易单号, yz, D参.D科目_商城_购买升级, "购买升级商品送商品附赠云值");
				下层角色 = 当前角色;
				if (交易.I价值 > 99) {
					// 第一次有效
					if (当前角色 == 0) {
						UserInfo 推荐人 = (UserInfo) 交易.u买方._nd父节点;
						if (推荐人 != null)
							推荐人.记用户云值(交易.l交易单号, D参.L商城_升级推荐奖, D参.D商城_升级推荐奖, "第一次购买升级产品,推荐人获得20云值");
						交易.u买方.记用户云值(交易.l交易单号, D参.L待激活云值, D参.D科目_商城_注册赠送, "第一次购买升级产品赠送100云值");

						下层角色 = 1;
						is升级 = true;
						r.设置商城角色(1);
					} // r.l日业绩
						// System.out.println(交易.I价值);
					r.l日增业绩 += 交易.I价值;
				}
				return false;
			}
			// 父节点 .....
			r.l日团队云值 += yz;
			r.l日团队业绩 += 交易.I价值;
			// 升级后联动升级
			if (is升级) {
				f101_商城_会员升级触发上级角色调整(r);
			}
			// 如果是直推节点
			if (r == 交易.u买方._nd父节点) {
				Long 云值 = D参.g商城_奖励(yz, D参.i商城_直接推荐奖比例);
				r.记用户云值(交易.l交易单号, 云值, D参.D科目_商城_购买直推奖,
						" 购买人:" + 交易.u买方._id + " ,推荐人直推奖= 商品赠送云值*" + D参.i商城_直接推荐奖比例 + "‰");
				下层角色 = 当前角色;
				return false;
			}
			// System.out.println(r._id);
			// 下角色,上角色,级差_平,
			// 动态更新上级角色
			if (下层角色 > 0) {
				if (下层角色 < 当前角色) {
					int 级差 = 0;
					for (int js = 下层角色; js < 当前角色; js++) {
						级差 += D参.D商城_购买奖极差[js];
					}
					云值奖金 += D参.g商城_奖励(yz, 级差);
					String msg = MyFun.join("当前角色:", D参.D商城角色[当前角色], ",下层角色:", D参.D商城角色[下层角色],
							"; 购买级差奖=赠送云值*" + 级差 + "‰");
					r.记用户云值(交易.l交易单号, 云值奖金, D参.D科目_商城_购买级差奖, msg);
					下层角色 = 当前角色;
				} else if (云值奖金 > 0 && 下层角色 == 当前角色) {// 平级最多拿一次
					云值奖金 = D参.g商城_购买_平级奖(云值奖金);
					r.记用户云值(交易.l交易单号, 云值奖金, D参.D科目_商城_购买平级奖,
							"当前角色:" + D参.D商城角色[当前角色] + " ;购买平级奖=级差奖*" + D参.D商城_购买平级奖比例 + "‰");
					云值奖金 = 0L;
					下层角色 = 当前角色;
				}
			}

			return false;
		}

	}

	// 用户购买升级商品后 升级vip时,触发所有上级节点角色调整
	public void f101_商城_会员升级触发上级角色调整(UserInfo u) {

		if (u.i商城角色 == 0) {
			// 升级角色
			return;
		} else if (u.i商城角色 == 1) {
			if ((u.i直推vip数 > D参.D主管条件[0] && u.i伞下vip数 > D参.D主管条件[1])
					|| (u.i伞下商家数 > D参.D主管条件[2] && u.i伞下vip数 > D参.D主管条件[3])) {
				u.设置商城角色(2);
			}
		} else if (u.i商城角色 == 2) {
			if ((u.至少n个直推用户旗下各m名x角色会员(D参.D店长条件[0], D参.D店长条件[1], 2))
					|| (u.i伞下商家数 > D参.D店长条件[2] && u.i伞下vip数 > D参.D店长条件[3])) {
				u.设置商城角色(3);
			}
		} else if (u.i商城角色 == 3) {
			if ((u.至少n个直推用户旗下各m名x角色会员(D参.D经理条件[0], D参.D经理条件[1], 3))
					|| (u.i伞下商家数 > D参.D经理条件[2] && u.i伞下vip数 > D参.D经理条件[3])) {
				u.设置商城角色(4);
			}
		} else if (u.i商城角色 == 4) {
			if ((u.至少n个直推用户旗下各m名x角色会员(D参.D直营店条件[0], D参.D直营店条件[1], 4))
					|| (u.i伞下商家数 > D参.D经理条件[2] && u.i伞下vip数 > D参.D经理条件[3])) {
				u.设置商城角色(5);
			}
		}

	}

	// 每次打赏时调用即可
	public void f200_打赏仓金(T打赏 ds) {
		if (ds.u打赏人.i系统角色 == 2) {// 如果是商户

			if (ds.u被打赏人.l仓金账户 > ds.i仓金)
				ds.u打赏人.记用户云值(ds.l打赏单号, ds.l云值 * D参.I打赏送商户云值 / D参.I打赏送会员云值, D参.D科目_商城_打赏商户, "打赏商户云值");
			ds.u被打赏人.记用户云值(ds.l打赏单号, ds.l云值, D参.D科目_商城_打赏用户, "打赏会员云值");
			ds.u打赏人.扣用户仓金(ds.l打赏单号, -ds.i仓金, D参.D科目_商城_打赏扣仓金, "打赏扣除商户仓金");

			// 被打赏人的直推人获得 ，打赏仓金的5% 奖金科目=22
			// 打赏商家的直推人获得， 打赏仓金5% 奖金科目=23
			UserInfo 推荐人 = (UserInfo) ds.u打赏人._nd父节点;
			if (推荐人 != null) {
				Long 仓金 = D参.g商城_奖励(ds.i仓金, D参.打赏推荐人奖励[0]);
				long 打赏仓金 = 推荐人.get可打赏仓金(仓金);
				if (打赏仓金 > 0) {
					推荐人.l日打赏仓金 += 打赏仓金;// 只能记在打赏人账上
					String msg = MyFun.join("打赏人的推荐人获得直推仓金奖=", D参.打赏推荐人奖励[0], "‰ * ", ds.i仓金);
					推荐人.奖励仓金扣云值(ds.l打赏单号, 打赏仓金, D参.D科目_商城_打赏直推奖, msg);
					推荐人.up2(0, new NB200_商城打赏送仓金(打赏仓金, ds));// 向上计算级差
				}
			}
			UserInfo 推荐人2 = (UserInfo) ds.u被打赏人._nd父节点;
			if (推荐人2 != null) {
				Long 仓金 = D参.g商城_奖励(ds.i仓金, D参.打赏推荐人奖励[1]);
				long 打赏仓金 = 推荐人2.get可打赏仓金(仓金);
				if (打赏仓金 > 0) {
					// 推荐人.i当日打赏仓金 += 仓金; //不能记在被打赏人账上
					String msg = MyFun.join("被打赏人的推荐人获得直推仓金奖=", D参.打赏推荐人奖励[1], "‰ * ", ds.i仓金);
					推荐人2.奖励仓金扣云值(ds.l打赏单号, 打赏仓金, D参.D科目_商城_被打赏直推奖, msg);
					推荐人2.up2(0, new NB200_商城打赏送仓金(打赏仓金, ds));// 向上计算级差
				}
			}
		}

	}

	class NB200_商城打赏送仓金 implements IDoEach1<MyNode<Integer, String>> {
		long 仓金奖金 = 0;
		int 下层角色 = 0;

		// UserInfo u会员;
		long l基准仓金 = 0;
		T打赏 打赏单;

		public NB200_商城打赏送仓金(long 仓金, T打赏 ds) {
			// u会员 = 会员;
			l基准仓金 = 仓金;
			打赏单 = ds;
		}

		@Override
		public boolean isOver(long ind, MyNode<Integer, String> obj) {
			UserInfo r = (UserInfo) obj;
			if (ind == 0) {
				下层角色 = r.i商城角色;
				return false;// 如果是自己,跳过
			}

			int 当前角色 = r.i商城角色;
			if (当前角色 < 2)
				return false;// 不到主管,不计算
			// 会员角色决定了级差,
			if (下层角色 < 当前角色) {
				int 级差 = 0;
				while (下层角色 < 当前角色) {
					级差 += D参.D商城_打赏极差[下层角色 - 1];
					下层角色++;
				}
				仓金奖金 += D参.g商城_奖励(l基准仓金, 级差);
				// 如果用户的云值不够,就不发仓金奖金
				long 打赏仓金 = r.get可打赏仓金(仓金奖金);
				if (打赏仓金 > 0) {
					String msg = MyFun.join("当前角色:", D参.D商城角色[当前角色], " 打赏仓金级差奖=", l基准仓金, " * ", 级差, "‰;");
					r.奖励仓金扣云值(打赏单.l打赏单号, 仓金奖金, D参.D科目_商城_打赏级差, msg);
				}
			} else if (仓金奖金 > 0 && 下层角色 == 当前角色) {
				String msg = MyFun.join("当前角色:", D参.D商城角色[当前角色], " 打赏仓金平级奖=", 仓金奖金, " * ", D参.D打赏仓金_平级, "‰;");
				仓金奖金 = D参.g商城_打赏仓金_平级(仓金奖金);
				long 打赏仓金 = r.get可打赏仓金(仓金奖金);
				if (打赏仓金 > 0) {
					r.奖励仓金扣云值(打赏单.l打赏单号, 仓金奖金, D参.D科目_商城_打赏平级, msg);
				}
				仓金奖金 = 0;
			}
			return false;
		}
	};

	public int i结算日期 = 0;
	public long 当天总云值 = 0;
	public long 当天打赏总仓金 = 0;
	public long 总云值 = 0;
	public long 当天总业绩 = 0;
	public long 总业绩 = 0;
	public int 总人数 = 0;// 有参与交易的人数
	public long 打赏总仓金 = 0;
	public Map<Integer, Integer> 各级人数 = new HashMap<>();
	public Map<Integer, Long> 各级业绩 = new HashMap<>();
	public Map<Integer, Long> 各级打赏仓金 = new HashMap<>();
	public Map<Integer, Long> 各级分红均值 = new HashMap<>();
	public int 代理人数 = 0;

	public void f300_商城_日结_初始化() {

		当天总云值 = 0;
		当天打赏总仓金 = 0;
		当天总业绩 = 0;
		总云值 = 0;
		总业绩 = 0;
		打赏总仓金 = 0;

		i结算日期 = MyFun.getYYYYMMDD();
		UserInfo._根节点.down((nd) -> {
			UserInfo us = (UserInfo) nd;
			if (us.l日赠云值 > 0) {
				当天总云值 += us.l日赠云值;
				总云值 += us.l累计到昨日云值 + us.l日赠云值;
			}
			us.print商城属性();
			if (us.l日增业绩 > 0) {
				当天总业绩 += us.l日增业绩;
				总业绩 += us.l累计到昨日业绩 + us.l日增业绩;
			}
			if (us.l日打赏仓金 > 0) {
				当天打赏总仓金 += us.l日打赏仓金;
				打赏总仓金 += us.l累计到昨日仓金 + us.l日打赏仓金;
			}

			if ((us.i分红级别 & UserInfo.D直营商家) == UserInfo.D直营商家)
				set各级值(UserInfo.D直营商家, us.l日增业绩, us.l日打赏仓金);
			if ((us.i分红级别 & UserInfo.D战区) == UserInfo.D战区)
				set各级值(UserInfo.D战区, us.l日增业绩, us.l日打赏仓金);
			if ((us.i分红级别 & UserInfo.D运营中心) == UserInfo.D运营中心)
				set各级值(UserInfo.D运营中心, us.l日增业绩, us.l日打赏仓金);

			if (us.i商户代理角色 > 0) {
				代理人数++;
			}

			us.up((nnd) -> {
				if (nnd == us)
					return;
				UserInfo unnd = (UserInfo) nnd;
				unnd.l日伞下打赏仓金 += us.l日打赏仓金;

			});
		}, null);

	}

	void set各级值(int 级别, long 业绩, long 仓金) {
		各级人数.put(级别, MyFun.nvlInt(各级人数.get(级别), 0) + 1);
		各级业绩.put(级别, MyFun.nvlLong(各级业绩.get(级别), 0) + 业绩);
		各级打赏仓金.put(级别, MyFun.nvlLong(各级打赏仓金.get(级别), 0) + 仓金);

	}

	public void f301_商城_日结_分红() {

		// 计算打赏分红
		// 打赏分红结算给 战区 运营中心等
		// 打赏分红以卖方打赏为基准
		long 均值 = D参.g商城_平均分红(当天打赏总仓金, D参.D商城_战区分红比[1], MyFun.nvlInt(各级人数.get(UserInfo.D战区), 0));
		各级分红均值.put(UserInfo.D战区, 均值);
		均值 = D参.g商城_平均分红(当天打赏总仓金, D参.D商城_运营中心分红比[1], MyFun.nvlInt(各级人数.get(UserInfo.D运营中心), 0));
		各级分红均值.put(UserInfo.D运营中心, 均值);
		均值 = D参.g商城_平均分红(当天打赏总仓金, D参.D商城_直营商家分红比[1], MyFun.nvlInt(各级人数.get(UserInfo.D直营商家), 0));
		各级分红均值.put(UserInfo.D直营商家, 均值);

		long 销毁仓金 = (D参.比例1000 - D参.D商城_战区分红比[0] - D参.D商城_战区分红比[1] - D参.D商城_运营中心分红比[0] - D参.D商城_运营中心分红比[1]
				- D参.D商城_直营商家分红比[0] - D参.D商城_直营商家分红比[1] - D参.打赏推荐人奖励[0] - D参.打赏推荐人奖励[1] - D参.打赏推荐人奖励[0]) / D参.比例1000
				* 当天打赏总仓金;

		UserInfo._根节点.down((nd) -> {
			UserInfo us = (UserInfo) nd;
			us.print商城属性();
			if (us.l日增业绩 > 0) {

				// 现金奖
				us.up2(0, new NB4_现金奖());
			}
			// 打赏分红
			long 仓金分红 = 0;
			if (us._id == 2) {// 分红公司不用扣公司 的云值
				仓金分红 = 当天打赏总仓金 * D参.D商城_平台分红 / D参.比例1000;
				us.奖用户仓金不扣云值(0, 仓金分红, D参.D科目_商城_打赏分红, "平台分红");
			}

			int 级别 = UserInfo.D战区;
			if ((us.i分红级别 & 级别) == 级别) {
				仓金分红 += 各级分红均值.get(级别);
				仓金分红 += D参.g商城_业绩分红(当天打赏总仓金, us.l日伞下打赏仓金, MyFun.nvlLong(各级打赏仓金.get(级别), 0), 级别);

				us.奖励仓金扣云值(0, us.get可打赏仓金(仓金分红), D参.D科目_商城_打赏分红, "战区分红");
			}

			级别 = UserInfo.D直营商家;
			if ((us.i分红级别 & 级别) == 级别) {
				仓金分红 += 各级分红均值.get(级别);
				仓金分红 += D参.g商城_业绩分红(当天打赏总仓金, us.l日伞下打赏仓金, MyFun.nvlLong(各级打赏仓金.get(级别), 0), 级别);
				us.奖励仓金扣云值(0, us.get可打赏仓金(仓金分红), D参.D科目_商城_打赏分红, "直营商家分红");
			}

			级别 = UserInfo.D运营中心;
			if ((us.i分红级别 & 级别) == 级别) {
				仓金分红 += 各级分红均值.get(级别);
				仓金分红 += D参.g商城_业绩分红(当天打赏总仓金, us.l日伞下打赏仓金, MyFun.nvlLong(各级打赏仓金.get(级别), 0), 级别);
				us.奖励仓金扣云值(0, us.get可打赏仓金(仓金分红), D参.D科目_商城_打赏分红, "运营中心分红");
			}

		}, null);
	}

//向上遍历 迭代计算现金奖和仓金分红
	class NB4_现金奖 implements IDoEach1<MyNode<Integer, String>> {
		public NB4_现金奖() {

			// System.out.println("业绩=" + 业绩);
		}

		long 现金奖 = 0L;
		long 运营现金奖 = 0L;
		long 战区现金奖 = 0L;
		long l业绩 = 0;
		int 角色 = 0;
		int 级1 = 0;
		int 级2 = 0;

		@Override
		public boolean isOver(long index, MyNode<Integer, String> nnd) {
			UserInfo uu = (UserInfo) nnd;
			if (index == 0) {
				l业绩 = uu.l日增业绩;
				return false;
			}
			if (l业绩 == 0) // 无业绩不需要遍历计算
				return true;
			int 比例 = 0;
			if (index == 1) {// 直推人现金奖
				比例 = D参.D商城_现金奖[0];
				角色 = 1;
			} else {// if (index > 1)
				// uu.i商城角色
				if (角色 == 1 && uu.i商城角色 == 2) {// 主管
					比例 = D参.D商城_现金奖[1];
					角色 = 2;
				} else if (角色 == 2 && uu.i商城角色 == 3) {// 主管
					比例 = D参.D商城_现金奖[2];
					角色 = 3;
				} else if (角色 == 3 && uu.i商城角色 == 4) {// 主管
					比例 = D参.D商城_现金奖[3];
					角色 = 4;
				} else if (角色 == 4 && uu.i商城角色 == 5) {// 主管
					比例 = D参.D商城_现金奖[4];
					角色 = 5;
				}
			}
			if (比例 > 0) {
				现金奖 = 现金奖 * 比例 / D参.比例1000;
				uu.记用户现金奖(index, 现金奖, D参.D科目_商城_现金奖, "按买方业绩*" + 比例 + "‰给予现金奖");
			}
//			战区：社群消费2％奖励，平级20％
//			运营中心：社群消费3％奖励，平级20％

			if ((uu.i分红级别 & UserInfo.D战区) == UserInfo.D战区) {
				if (级1 == 0) {// 消费2%
					战区现金奖 = l业绩 * D参.D商城_战区现金奖[0] / D参.比例1000;
					uu.记用户现金奖(0, 战区现金奖, D参.D科目_商城_现金奖, "战区现金奖=社群消费*" + D参.D商城_战区现金奖[0] + "‰");
					级1 = 1;
				} else if (级1 == 1) {// 平级
					战区现金奖 = 战区现金奖 * D参.D商城_战区现金奖[1] / D参.比例1000;
					uu.记用户现金奖(0, 战区现金奖, D参.D科目_商城_现金奖, "战区现金平级奖=上一级运营中心现金奖*" + D参.D商城_运营中心现金奖[1] + "‰");
					级1 = 2;
				}
			}

			if ((uu.i分红级别 & UserInfo.D运营中心) == UserInfo.D运营中心) {
				if (级2 == 0) {
					运营现金奖 = l业绩 * D参.D商城_运营中心现金奖[0] / D参.比例1000;
					uu.记用户现金奖(0, 运营现金奖, D参.D科目_商城_现金奖, "运营中心现金奖=社群消费*" + D参.D商城_运营中心现金奖[0] + "‰");
					级2 = 1;
				} else if (级2 == 1) {
					运营现金奖 = 运营现金奖 * D参.D商城_运营中心现金奖[1] / D参.比例1000;
					uu.记用户现金奖(0, 运营现金奖, D参.D科目_商城_现金奖, "运营中心现金平级奖=上一级运营中心现金奖*" + D参.D商城_运营中心现金奖[1] + "‰");
					级2 = 2;
				}

			}

			return false;
		}
	}

	public void f309_商城_日结_结尾() {
		UserInfo._根节点.down((nd) -> {
			UserInfo u = (UserInfo) nd;
			u.l累计到昨日云值 += u.l日赠云值;
			u.l累计到昨日业绩 += u.l日增业绩;
			u.l累计到昨日仓金 += u.l日打赏仓金;
			// 批量更新到用户表
		}, null);
	}

	public void f400_商城_日结_定时空投仓金() {

		int 运营中心人数 = 各级人数.get(UserInfo.D运营中心);
		String 个人msg1 = MyFun.join("每日空投给个人_按日业绩分=日赠云值 / 当天总云值 * l空投仓金 *个人仓金分红比1(",
				(float) D参.D空投_个人仓金分红比[0] / D参.比例1000, ")");
		String 个人msg2 = MyFun.join("每日空投给个人_按总业绩分=个人累计云值 / 总云值 * 空投仓金 * 个人仓金分红比2(",
				(float) D参.D空投_个人仓金分红比[1] / D参.比例1000, ")");
		//
		long 运营中心平分仓金 = D参.g空投_平均仓金(D参.l空投仓金, D参.D空投_运营中心分红比[1], 运营中心人数);
		String 运营中心msg1 = MyFun.join("每日空投给运营中心_按日业绩分=l日团队业绩/当天总业绩*空投总额*", (float) D参.D空投_运营中心分红比[0] / D参.比例1000);
		String 运营中心msg2 = MyFun.join("每日空投给运营中心_平分= 空投仓金* ", (float) D参.D空投_运营中心分红比[1] / D参.比例1000, "/", 运营中心人数);

		long 代理平分仓金 = D参.g空投_平均仓金(D参.l空投仓金, D参.D空投_代理分红比[1], 代理人数);
		String 代理msg1 = MyFun.join("每日空投给代理_按日业绩分=l日团队业绩/当天总业绩*空投总额*", (float) D参.D空投_代理分红比[0] / D参.比例1000);
		String 代理msg2 = MyFun.join("每日空投给代理_平分= 空投仓金* ", (float) D参.D空投_代理分红比[1] / D参.比例1000, "/", 代理人数);
		UserInfo._根节点.down((nd) -> {
			UserInfo u = (UserInfo) nd;
			if (u.l日赠云值 == 0)
				return;
			// 空投给个人
			long 累计云值 = u.get累计云值();
			int 仓金 = (int) (u.l日赠云值 / 当天总云值 * D参.l空投仓金 * D参.D空投_个人仓金分红比[0] / D参.比例1000);
			if (累计云值 > 仓金) {
				u.奖励仓金扣云值(0, 仓金, D参.D科目_商城_空投, 个人msg1);
			}
			仓金 = (int) (累计云值 / 总云值 * D参.l空投仓金 * D参.D空投_个人仓金分红比[1] / D参.比例1000);
			if (累计云值 > 仓金) {
				u.奖励仓金扣云值(0, 仓金, D参.D科目_商城_空投, 个人msg2);
			}

			// 空投给运营中心
			if ((u.i分红级别 & UserInfo.D运营中心) == UserInfo.D运营中心) {
				if (当天总业绩 > 0) {
					仓金 = (int) (u.l日团队业绩 / 当天总业绩 * D参.l空投仓金 * D参.D空投_运营中心分红比[0] / D参.比例1000);
					if (累计云值 > 仓金 + 运营中心平分仓金) {
						u.奖励仓金扣云值(0, 仓金, D参.D科目_商城_空投, 运营中心msg1);
						u.奖励仓金扣云值(0, 运营中心平分仓金, D参.D科目_商城_空投, 运营中心msg2);
					}
				}
			}
			// 空投给商户代理
			if (u.i商户代理角色 > 0) {
				if (当天总业绩 > 0) {
					仓金 = (int) (u.l日团队业绩 / 当天总业绩 * D参.l空投仓金 * D参.D空投_代理分红比[0] / D参.比例1000);
					if (累计云值 > 仓金 + 代理平分仓金) {

						u.奖励仓金扣云值(0, 仓金, D参.D科目_商城_空投, 代理msg1);
						u.奖励仓金扣云值(0, 代理平分仓金, D参.D科目_商城_空投, 代理msg2);
					}
				}
			}
		}, null);
		// 1.定时获取(自身云值/全网总云值*空投仓金 // 自身云值-本次获取仓金*仓金价格) 保留12位小数

	}

	public void f501_止拍_日释放() {
		//插入待释放记录
		long 时间戳=MyFun.getMs();
		//遍历待释放记录
		for (T释放 sf:待释放记录) {
			sf.f释放(时间戳);
			//如果释放账户==0 从释放记录表中标记失效
		}
	}

}
